package web.sso.common.collections;

import web.sso.common.throwable.ConstructorNotAvailableError;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * DATE: 2020/1/19
 * TIME: 4:01 下午
 *
 * @author：huangliming
 */
public class Maps {

    /**
     * 构造器不允许调用
     * 抛出异常目的是防止反射获取
     */
    private Maps() {
        throw new ConstructorNotAvailableError(Maps.class);
    }

    /**
     * 判断map是否非空
     * @param map
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> boolean notEmpty(Map<K, V> map) {
        return map != null && !(map.isEmpty());
    }

    /**
     * 判断map是否为空
     * @param map
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> boolean isEmpty(Map<K, V> map) {
        return !notEmpty(map);
    }

    /**
     * 遍历操作value
     * @param map
     * @param mapper
     */
    public static <K, V> void mapValues(Map<K, V> map, Function<V, V> mapper) {
        map.entrySet().forEach(entry -> {
            V value = entry.getValue();
            V newValue = mapper.apply(value);
            entry.setValue(newValue);
        });
    }

    /**
     * 遍历操作key
     * @param map
     * @param mapper
     */
    public static <K, V> void mapKeys(Map<K, V> map, Function<K, K> mapper) {
        map.keySet().forEach(key -> {
            V value = map.get(key);
            K newKey = mapper.apply(key);
            map.remove(key);
            map.put(newKey, value);
        });
    }

    /**
     * 获取一个map的key的集合
     * @param map
     * @return
     */
    public static <K, V> Set<K> keySet(Map<K, V> map) {
        return map.keySet();
    }

    /**
     * 获取一个map的value的集合
     * @param map
     * @return
     */
    public static <K, V> Set<V> valueSet(Map<K, V> map) {
        Set<V> set = new HashSet<>();
        map.forEach((k, v) -> set.add(v));
        return set;
    }

    /**
     * 重映射map
     * @param map
     * @param keyMapper
     * @param valueMapper
     * @return
     */
    public static <K, V, K1, V1> MapTransfer<K, V, K1, V1> reMap(
            Map<K, V> map,
            Function<K, K1> keyMapper,
            Function<V, V1> valueMapper
    ) {
        return new MapTransfer<>(map, keyMapper, valueMapper);
    }

    /**
     * transfer实现类
     */
    public static class MapTransfer<K, V, K1, V1> {

        private Map<K, V> map;
        private Function<K, K1> keyMapper;
        private Function<V, V1> valueMapper;

        MapTransfer(Map<K, V> map, Function<K, K1> keyMapper, Function<V, V1> valueMapper) {
            this.map = map;
            this.keyMapper = keyMapper;
            this.valueMapper = valueMapper;
        }

        /**
         * 将map重影射为一个HashMap
         * @return
         */
        public HashMap<K1, V1> hashMap() {
            HashMap<K1, V1> hashMapNew = new HashMap<>(map.size());
            doRebuild(hashMapNew);
            return hashMapNew;
        }

        /**
         * 将map重映射为一个线程安全的HashMap
         * @return
         */
        public ConcurrentHashMap<K1, V1> concurrentHashMap() {
            ConcurrentHashMap<K1, V1> concurrentHashMapNew = new ConcurrentHashMap<>(map.size());
            doRebuild(concurrentHashMapNew);
            return concurrentHashMapNew;
        }

        /**
         * 将map重映射为一个LinkedHashMap
         * @return
         */
        public LinkedHashMap<K1, V1> linkedHashMap() {
            LinkedHashMap<K1, V1> linkedHashMapNew = new LinkedHashMap<>(map.size());
            doRebuild(linkedHashMapNew);
            return linkedHashMapNew;
        }

        /**
         * 重映射核心实现代码
         * @param reMap
         */
        private void doRebuild(Map<K1, V1> reMap) {
            map.forEach((k, v) -> reMap.put(keyMapper.apply(k), valueMapper.apply(v)));
        }
    }
}
